var request = require('request');
var moment = require('moment');
moment.locale('zh-cn');

class TComm {

    static httpCall(aUrl, aMethod, aHeaders, aPs, aBody) {
        return new Promise((success, faild) => {
            try {
                var callUrl = aUrl;
                if (aPs && aPs != null && Object.keys(aPs) && Object.keys(aPs).length > 0) {
                    callUrl += callUrl.indexOf("?") > 0 ? "&" : "?";
                    callUrl += "randtm=" + Math.random();
                    Object.keys(aPs).forEach(p => {
                        callUrl += "&" + p + "=" + aPs[p];
                    })
                }

                var opts = {
                    url: callUrl,
                    method: aMethod
                }

                if (aBody && aBody != null) {
                    opts.body = aBody;
                }

                request(opts, (err, resp, result) => {
                    success({
                        err: err,
                        resp: resp,
                        result: result
                    })
                })
            } catch (Exce) {
                console.log(Exce);
                success(null);
            }
        })
    }
    static writeDB(aDbUrl, dbName, tableName, tags, fields, timestampe) {
        return new Promise((success, faild) => {
            try {
                var ps = {
                    db: dbName
                };
                var tagDatas = [];
                Object.keys(tags).forEach(t => {
                    tagDatas.push(t + "=" + tags[t]);
                })
                var fieldDatas = [];
                Object.keys(fields).forEach(f => {
                    var v = fields[f];
                    if (v && v != null) {
                        fieldDatas.push(f + "=" + fields[f]);
                    }
                })
                var body = tableName + "," + tagDatas.join(",") + ' ' + fieldDatas.join(",") + " " + timestampe;
                var url = aDbUrl + "/write";
                TComm.httpCall(url, "POST", {}, ps, body).then(res => {
                    success(res);
                })
            } catch (Exce) {
                console.log(Exce);
                success(null);
            }
        })
    }
    static getTimestampe(strTime) {
        var res = (new Date()).getTime() * 1000 * 1000;
        try {
            res = (new Date(Date.parse(strTime.replace(/-/g, "/")))) * 1000 * 1000
        } catch (er) {
            console.log(er);
        }
        return res;
    }
}

class TDataItem {
    constructor() {
        this.code = "";
        this.time = "";
        this.fields = {
            "pm10": null,
            "pm25": null,
            "tsp": null,
            "so2": null,
            "no2": null,
            "co": null,
            "o3": null,
            "ws": null,
            "wd": null,
            "ta": null,
            "ua": null,
            "pm10_aqi": null,
            "pm25_aqi": null,
            "so2_aqi": null,
            "no2_aqi": null,
            "co_aqi": null,
            "o3_aqi": null,
            "aqi": null
        };
        this.firstPollutant = "";
    }
    getFirstPollutant() {
        var res = 0;
        try {
            var item = this;
            if (item.fields.api != null && item.fields.api > 0) {
                var keys = Object.keys(item.fields);
                for (var i = 0; i < keys.length; i++) {
                    var f = keys[i];
                    var value = item[f];
                    var flag = f.indexOf('_api') >= 0 & value && value != null && value == item.fields.api;
                    if (flag) {
                        res = i;
                    }
                }
            }
        } catch (er) {
            console.log(er);
        }
        return res;
    }
    setDataItemValues(srcItem) {
        var res = new TDataItem();
        try {} catch (er) {
            console.log(er);
        }
        return res;
    }
    write2DB(aDbUrl, dbName, tableName) {
        return new Promise((success, faild) => {
            try {
                var item = this;
                var tags = {
                    code: item.code
                };
                var tm = TComm.getTimestampe(item.time);
                var fields = JSON.parse(JSON.stringify(item.fields));
                fields.firstPollutant = item.getFirstPollutant();
                TComm.writeDB(aDbUrl, dbName, tableName, tags, fields, tm).then(_ => {
                    success();
                });

            } catch (er) {
                console.log(er);
                success();
            }
        })
    }
}

class TImport {
    static getRealDataItems(apiUrl) {
        return new Promise((success, faild) => {
            var res = [];
            try {
                TComm.httpCall(apiUrl, "GET", null, {}, null).then(datas => {
                    try {
                        var srcItems = JSON.parse(datas.result);
                        if (srcItems.Result) {
                            var resItems = {}
                            srcItems.realDatas.forEach(ri => {
                                var key = ri.mn + '_' + ri.time;
                                var item = resItems[key];
                                if (!item) {
                                    item = new TDataItem();
                                    item.time = ri.time;
                                    item.code = ri.mn;
                                    resItems[key] = item;
                                }
                            })
                        }
                        res = Object.values(resItems);
                        success(res);

                    } catch (eer) {
                        console.log(eer);
                        success(res);
                    }

                })
            } catch (Exce) {
                console.log(Exce);
                success(res);
            }
        })
    }
    static getRealDataItems(apiUrl) {
        return new Promise((success, faild) => {
            var res = [];
            try {
                TComm.httpCall(apiUrl, "GET", null, {}, null).then(datas => {
                    try {
                        var srcItems = JSON.parse(datas.result);
                        if (srcItems.Result) {
                            var resItems = {}
                            srcItems.realDatas.forEach(ri => {
                                var key = ri.mn + '_' + ri.time;
                                var item = resItems[key];
                                if (!item) {
                                    item = new TDataItem();
                                    item.time = ri.time;
                                    item.code = ri.mn;
                                    resItems[key] = item;
                                }
                                Object.keys(item.fields).forEach(f => {
                                    var v = ri[f];
                                    if (v && v != null && v > 0) {
                                        item.fields[f] = v * 1.0;
                                    }
                                })
                            })
                        }
                        res = Object.values(resItems).filter(r => {
                            var flag = false;
                            Object.keys(r.fields).forEach(f => {
                                var v = r.fields[f];
                                if (v && v != null && v > 0) {
                                    flag = true;
                                }
                            })
                            return flag;
                        });
                        success(res);

                    } catch (eer) {
                        console.log(eer);
                        success(res);
                    }

                })
            } catch (Exce) {
                console.log(Exce);
                success(res);
            }
        })
    }
    static getHisDataItems(apiUrl, start, end, code, dateType) {
        return new Promise((success, faild) => {
            var res = [];
            try {
                var aUrl = apiUrl.replace("{dateType}", dateType);
                aUrl = aUrl.replace("{code}", code);
                aUrl = aUrl.replace("{start}", start);
                aUrl = aUrl.replace("{end}", end);

                var ps = {
                    startDate: start,
                    endDate: end
                }
                TComm.httpCall(aUrl, "GET", null, {}, null).then(datas => {
                    try {
                        var srcItems = JSON.parse(datas.result);
                        if (srcItems.Result) {
                            var resItems = {}
                            srcItems.realDatas.forEach(ri => {
                                ri.mn = code;
                                var key = ri.mn + '_' + ri.time;
                                var item = resItems[key];
                                if (!item) {
                                    item = new TDataItem();
                                    item.time = ri.time;
                                    item.code = ri.mn;
                                    resItems[key] = item;
                                }
                                Object.keys(item.fields).forEach(f => {
                                    var v = ri[f];
                                    if (v && v != null && v > 0) {
                                        item.fields[f] = v * 1.0;
                                    }
                                })
                            })
                        }
                        res = Object.values(resItems).filter(r => {
                            var flag = false;
                            Object.keys(r.fields).forEach(f => {
                                var v = r.fields[f];
                                if (v && v != null && v > 0) {
                                    flag = true;
                                }
                            })
                            return flag;
                        });
                        success(res);

                    } catch (eer) {
                        console.log(eer);
                        success(res);
                    }

                })
            } catch (Exce) {
                console.log(Exce);
                success(res);
            }
        })
    }
    static write2DB(dateItems, aDbUrl, dbName, tableName) {
        return new Promise((success, faild) => {
            try {
                var items = dateItems;
                var write2DB = function() {
                    if (items.length > 0) {
                        var item = items.shift();
                        item.write2DB(aDbUrl, dbName, tableName).then(_ => {
                            write2DB(aDbUrl, dbName, tableName);
                        })
                    } else {
                        success();
                    }
                }
                write2DB();
            } catch (Exce) {
                console.log(Exce);
                success();
            }
        })
    }
}

class TImportApp {
    constructor() {
        this.config = {
            apiUrl: {
                realUrl: "http://123.234.35.141:1008/ashx/dataManage/HCInterface.ashx?action=getNewData&datatype=minute",
                hisUrl: "http://123.234.35.141:1008/ashx/dataManage/HCInterface.ashx?action=getHistoryData&datatype={dateType}&startDate={start}&endDate={end}&mn={code}",
                //hisUrl: "http://123.234.35.141:1008/ashx/dataManage/HCInterface.ashx?action=getHistoryData&datatype={dateType}&mn={code}"
            },
            db: {
                dbUrl: "http://10.8.101.141:8086",
                dbName: "gangkou_sd"
            }
        }
    }
    import () {
        var me = this;
        try {
            var acImport = function() {
                return new Promise((success, faild) => {
                    try {
                        var hourStart = moment((new Date()).getTime() - 4 * 3600 * 1000).format('yyyy-MM-DD HH:00:00');
                        var hourEnd = moment((new Date()).getTime() + 1 * 3600 * 1000).format('yyyy-MM-DD HH:00:00');
                        var dayStart = moment((new Date()).getTime() - 2 * 3600 * 24 * 1000).format('yyyy-MM-DD');
                        var dayEnd = moment((new Date()).getTime() + 1 * 3600 * 24 * 1000).format('yyyy-MM-DD');
                        var codes = [];
                        console.log('---------------------------------------------------------------');
                        console.log('h:', hourStart, ' - ', hourEnd, 'd:', dayStart, ' - ', dayEnd)
                        TImport.getRealDataItems(me.config.apiUrl.realUrl).then(realItems => {
                            var realCount = realItems.length;
                            realItems.forEach(i => {
                                codes.push(i.code);
                            })
                            TImport.write2DB(realItems, me.config.db.dbUrl, me.config.db.dbName, "T_R").then(_ => {
                                console.log('import real.', realCount);
                                var importHis = function() {
                                    if (codes.length > 0) {
                                        var code = codes.shift();
                                        TImport.getHisDataItems(me.config.apiUrl.hisUrl, hourStart, hourEnd, code, "hour").then(hourItems => {
                                            return TImport.write2DB(hourItems, me.config.db.dbUrl, me.config.db.dbName, "T_H");
                                        }).then(_ => {
                                            console.log('import hour data.', code);
                                            return TImport.getHisDataItems(me.config.apiUrl.hisUrl, dayStart, dayEnd, code, "day")
                                        }).then(dayItems => {
                                            return TImport.write2DB(dayItems, me.config.db.dbUrl, imp.config.db.dbName, "T_D");
                                        }).then(_ => {
                                            console.log('import day data.', code);
                                            importHis();
                                        })
                                    } else {
                                        success();
                                    }
                                }
                                importHis();
                            });
                        })
                    } catch (eer) {
                        console.log(eer);
                        success();
                    }
                })
            }

            acImport().then(_ => {
                setTimeout(() => {
                    me.import();
                }, 5 * 60 * 1000);
            })
        } catch (er) {
            console.log(er);
        }
    }
}

var realUrl = "http://123.234.35.141:1008/ashx/dataManage/HCInterface.ashx?action=getNewData&datatype=minute";
var hisUrl = "http://123.234.35.141:1008/ashx/dataManage/HCInterface.ashx?action=getHistoryData&datatype={dateType}&startDate={start}&endDate={end}&mn={code}";

//(new TImportApp()).import();

var imp = new TImportApp();
imp.import();